package com.boot.database.initialization;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.sql.init.DatabaseInitializationMode;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;

/**
 * @author 霜寒 <1621856595@qq.com>
 * @date 2021/8/23 23:50
 **/
@Slf4j
@Configuration
public class DatabaseInitializationAutoConfiguration {

    @Value("${spring.sql.init.mode}")
    private DatabaseInitializationMode initializationMode;

    @Value("${spring.sql.init.code-initialization}")
    private boolean codeInitialization;

    private final DatabaseInitialization[] initializations;

    public DatabaseInitializationAutoConfiguration(@Autowired(required = false) DatabaseInitialization[] initializations) {
        this.initializations = initializations;
    }

    @EventListener(ContextRefreshedEvent.class)
    public void onContextRefreshedEvent(ContextRefreshedEvent e) {
        if (DatabaseInitializationMode.NEVER.equals(initializationMode)
                && codeInitialization) {
            Arrays.sort(initializations, Comparator.comparingInt(DatabaseInitialization::order));
            log.info("Database Initialization: {}", Arrays.toString(initializations));
            Set<Class<? extends DatabaseInitialization>> classSet = new HashSet<>(initializations.length / 2);
            for (DatabaseInitialization initialization : initializations) {
                if (!classSet.contains(initialization.getClass())) {
                    Set<Class<? extends DatabaseInitialization>> includes = initialization.includes();
                    if (null != includes) {
                        classSet.addAll(includes);
                    }
                    initialization.initialization();
                }
            }
        }
    }
}
